package ldh.im.web.controller;

import ldh.common.json.JsonViewFactory;
import ldh.im.web.config.AesService;
import ldh.im.web.pojo.Authority;
import ldh.im.web.pojo.Role;
import ldh.im.web.pojo.User;
import ldh.im.web.pojo.where.AuthorityWhere;
import ldh.im.web.pojo.where.RoleWhere;
import ldh.im.web.service.AuthorityService;
import ldh.im.web.service.RoleService;
import ldh.im.web.service.UserService;
import ldh.im.web.util.NumberUtil;
import ldh.im.web.util.UserUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.util.*;
import java.util.stream.Collectors;

@Controller
@RequestMapping("manager")
public class ManagerController {

    @Resource(name = "userService")
    private UserService userService;
    @Resource(name = "roleService")
    private RoleService roleService;
    @Resource(name = "aesService")
    private AesService aesService;
    @Resource(name = "authorityService")
    private AuthorityService authorityService;

    @RequiresPermissions("manager:changePassword")
    @RequestMapping(method = RequestMethod.GET, value = "/changePassword/json/{userId}")
    @ResponseBody
    public String changePassword(@PathVariable Long userId) throws Exception {
        User user = userService.getById(userId);
        if (user == null) {
            return JsonViewFactory.create().fail("参数错误").toJson();
        }
        String newPassword = userService.changePassword(userId);
        return JsonViewFactory.create().put("newPassword", newPassword).toJson();
    }

    @RequiresPermissions("manager:userAuthorize")
    @RequestMapping(method = RequestMethod.GET, value = "/userAuthorize/{userId}")
    public String userAuthorize(@PathVariable Long userId, Model model) throws Exception {
        User user = userService.getManyRolesById(userId);
        Objects.requireNonNull(user);
        if (StringUtils.isNoneEmpty(user.getPhone())) {
            user.setMaskPhone(NumberUtil.maskPhone(aesService.decrypt(user.getPhone())));
        }
        if (StringUtils.isNoneEmpty(user.getEmail())) {
            user.setMaskEmail(NumberUtil.maskEmail(aesService.decrypt(user.getEmail())));
        }

        RoleWhere roleWhere = new RoleWhere();
        List<Role> roleList = roleService.getAllRoles(roleWhere);

        Map<String, Role> roleMap = user.getRoles().stream().collect(Collectors.toMap(role->role.getId() + "", role->role));

        model.addAttribute("user", user);
        model.addAttribute("roleMap", roleMap);
        model.addAttribute("roleList", roleList);
        model.addAttribute("active", "user");
        return "manager/userAuthorize";
    }

    @RequiresPermissions("manager:userAuthorize_view")
    @RequestMapping(method = RequestMethod.GET, value = "/userAuthorizeView/{userId}")
    public String viewUserAuthorize(@PathVariable Long userId, Model model) throws Exception {
        userAuthorize(userId, model);
        return "manager/userAuthorizeView";
    }

    @ResponseBody
    @RequiresPermissions("manager:userAuthorize")
    @RequestMapping(method = RequestMethod.POST, value = "/userAuthorize/save/json/{userId}")
    public String saveUserAuthorize(@PathVariable Long userId, @RequestParam(name="roles", defaultValue = "") List<Long> roles, Model model) {
        User user = userService.getManyRolesById(userId);
        Objects.requireNonNull(user);
        Map<Long, Long> roleMap = roles.stream().collect(Collectors.toMap(roleId->roleId, roleId->roleId));
        Map<Long, Role> existedRoleMap = user.getRoles().stream().filter(role->roleMap.containsKey(role.getId())).collect(Collectors.toMap(Role::getId, role->role));
        List<Role> deleteRoleList = user.getRoles().stream().filter(role->!roleMap.containsKey(role.getId())).collect(Collectors.toList());

        List<Long> notExistedList = roles.stream().filter(roleId->!existedRoleMap.containsKey(roleId)).collect(Collectors.toList());
        List<Role> insertRoleList = new ArrayList<>();
        if (notExistedList.size() > 0) {
            insertRoleList = roleService.getByIds(notExistedList);
        }
        Objects.equals(deleteRoleList.size() + existedRoleMap.size(), user.getRoles().size());
        Objects.equals(existedRoleMap.size() + insertRoleList.size(), roles.size());

        userService.userAuthorize(user, deleteRoleList, insertRoleList);
        return JsonViewFactory.create().toJson();
    }



    @RequiresPermissions("manager:roleAuthorize")
    @RequestMapping(method = RequestMethod.GET, value = "/roleAuthorize/{roleId}")
    public String roleAuthorize(@PathVariable Long roleId, Model model) throws Exception {
        Role role = roleService.getManyAuthoritysById(roleId);
        Objects.requireNonNull(role);


        Map<String, Authority> authorityMap = role.getAuthoritys().stream().collect(Collectors.toMap(authority->authority.getId() + "", authority->authority));
//        Set<Long> moduleIdSet = role.getAuthoritys().stream().map(authority -> authority.getModule().getId()).collect(Collectors.toSet());
//        List<Module> moduleList = moduleService.getByIds(moduleIdSet);

        AuthorityWhere authorityWhere = new AuthorityWhere();
        List<Authority> authorityList = authorityService.getAllAuthoritys(authorityWhere);

        Map<String, List<Authority>> authorityGroupMap = authorityList.stream().collect(Collectors.groupingBy(authority-> {
            String[] as = authority.getName().split(":");
            if (as.length > 0) return as[0];
            return authority.getName();
        }));

        model.addAttribute("role", role);
        model.addAttribute("authorityMap", authorityMap);
        model.addAttribute("authorityGroupMap", authorityGroupMap);
        model.addAttribute("active", "role");
        return "manager/roleAuthorize";
    }

    @RequiresPermissions("manager:roleAuthorize_view")
    @RequestMapping(method = RequestMethod.GET, value = "/roleAuthorizeView/{roleId}")
    public String viewRoleAuthorize(@PathVariable Long roleId, Model model) throws Exception {
        roleAuthorize(roleId, model);
        return "manager/roleAuthorizeView";
    }

    private String groupAuthority(Authority authority) {
        String[] splits = new String[] {"_", "-", ":"};
        for(String split : splits) {
            int index = authority.getName().indexOf(split);
            if (index > 0) {
                return authority.getName().substring(0, index);
            }
        }
        int t = -1, findex = 0, sindex = 0;
        for (char c : authority.getName().toCharArray()) {
            t++;
            if (t == 0) continue; // 第一个大写字母忽略
            if ((char)c>='A'&&(char)c<='Z') {
                if (findex == 0) findex = t;
                if (findex != 0 && sindex != 0) sindex = t;
            }
        }
        if (sindex > 0) return authority.getName().substring(0, sindex);
        if (findex > 0) return authority.getName().substring(0, findex);
       return authority.getName().substring(0, 2);
    }

    @ResponseBody
    @RequiresPermissions("manager:roleAuthorize")
    @RequestMapping(method = RequestMethod.POST, value = "/roleAuthorize/save/json/{roleId}")
    public String saveRoleAuthorize(@PathVariable Long roleId, @RequestParam(name="authoritys", defaultValue = "") List<Long> authoritys, Model model) {
        Role role = roleService.getManyAuthoritysById(roleId);
        Objects.requireNonNull(role);
        Map<Long, Long> authorityMap = authoritys.stream().collect(Collectors.toMap(authorityId->authorityId, authorityId->authorityId));
        Map<Long, Authority> existedAuthorityMap = role.getAuthoritys().stream().filter(authority->authorityMap.containsKey(authority.getId())).collect(Collectors.toMap(Authority::getId, authority->authority));
        List<Authority> deleteAuthorityList = role.getAuthoritys().stream().filter(authority->!authorityMap.containsKey(authority.getId())).collect(Collectors.toList());

        List<Long> notExistedList = authoritys.stream().filter(authorityId->!existedAuthorityMap.containsKey(authorityId)).collect(Collectors.toList());
        List<Authority> insertAuthorityList = new ArrayList<>();
        if (notExistedList.size() > 0) {
            insertAuthorityList = authorityService.getByIds(notExistedList);
        }
        Objects.equals(deleteAuthorityList.size() + existedAuthorityMap.size(), role.getAuthoritys().size());
        Objects.equals(existedAuthorityMap.size() + insertAuthorityList.size(), authoritys.size());

        roleService.roleAuthorize(role, deleteAuthorityList, insertAuthorityList);
        return JsonViewFactory.create().toJson();
    }


    /**************************************模块分配角色**********************************/
    @RequiresPermissions("manager:moduleAuthorize")
    @RequestMapping(method = RequestMethod.GET, value = "/moduleAuthorize/{moduleId}")
    public String moduleAuthorize(@PathVariable Long moduleId, Model model, HttpSession httpSession) throws Exception {
        User loginUser = UserUtil.getLoginUser(httpSession);


        RoleWhere roleWhere = new RoleWhere();
        List<Role> roleList = roleService.getAllRoles(roleWhere);

        model.addAttribute("roleList", roleList);
        model.addAttribute("active", "module");
        return "manager/moduleAuthorize";
    }

    @RequiresPermissions("manager:moduleAuthorize_view")
    @RequestMapping(method = RequestMethod.GET, value = "/moduleAuthorizeView/{moduleId}")
    public String viewModuleAuthorize(@PathVariable Long moduleId, Model model, HttpSession httpSession) throws Exception {
        moduleAuthorize(moduleId, model, httpSession);
        return "manager/moduleAuthorizeView";
    }

    /*************************************清楚登录失败次数**************************/
    // 清楚登录失败次数
    @ResponseBody
    @RequiresPermissions("user:clear_login")
    @RequestMapping(method = RequestMethod.GET, value = "/clearLoginErrorNum/json/{userId}")
    public String clearLoginErrorNum(@PathVariable(name="userId") Long userId) throws Exception {
        User user = userService.getById(userId);
        int loginErrorNum = getLoginErrorNum(user.getUserName());
        if (loginErrorNum > 0) {
            cleanLoginErrorNum(user.getUserName());
        } else {
            loginErrorNum = getLoginErrorNum(user.getEmail());
            if (loginErrorNum > 0) {
                cleanLoginErrorNum(user.getEmail());
            } else {
                loginErrorNum = getLoginErrorNum(user.getPhone());
                if (loginErrorNum > 0) {
                    cleanLoginErrorNum(user.getPhone());
                }
            }
        }

        return JsonViewFactory.create()
                .toJson();
    }

    private int getLoginErrorNum(String key) {
//        Cache cache = cacheManager.getCache(CacheType.LoginErrorNum.getValue());
//        Element element = cache.get(key);
//        if (element != null) {
//            Integer value = (Integer) element.getObjectValue();
//            return value;
//        }
        return 0;
    }

    private void cleanLoginErrorNum(String key) {
//        Cache cache = cacheManager.getCache(CacheType.LoginErrorNum.getValue());
//        cache.remove(key);
    }
}
